using System;
using System.Collections.Generic;
using System.Linq;

namespace MT5Trade.Models
{
    /// <summary>
    /// 波动率聚类分析和趋势判断类
    /// 实现K-means聚类算法识别不同波动率状态，基于GARCH预测结果进行趋势分析
    /// 严格遵循时间序列分析原理，避免过度拟合
    /// </summary>
    public class VolatilityClusterAnalyzer
    {
        #region 算法常量定义

        /// <summary>聚类数量 - 低、中、高三种波动状态</summary>
        public const int VOLATILITY_CLUSTERS = 3;

        /// <summary>K-means最大迭代次数</summary>
        public const int KMEANS_MAX_ITERATIONS = 100;

        /// <summary>K-means收敛阈值</summary>
        public const double KMEANS_CONVERGENCE_TOLERANCE = 1e-6;

        /// <summary>最小样本数量要求</summary>
        public const int MIN_VOLATILITY_SAMPLES = 50;

        /// <summary>趋势强度计算窗口</summary>
        public const int TREND_STRENGTH_WINDOW = 20;

        /// <summary>状态转移平滑系数</summary>
        public const double TRANSITION_SMOOTHING_FACTOR = 0.1;

        /// <summary>低波动阈值系数</summary>
        public const double LOW_VOLATILITY_THRESHOLD = 0.8;

        /// <summary>高波动阈值系数</summary>
        public const double HIGH_VOLATILITY_THRESHOLD = 1.2;

        /// <summary>趋势强度阈值</summary>
        public const double TREND_STRENGTH_THRESHOLD = 0.6;

        /// <summary>计算精度常量</summary>
        public const double CALCULATION_PRECISION = 1e-12;

        #endregion

        #region 数据结构定义

        /// <summary>
        /// 波动率状态枚举
        /// </summary>
        public enum VolatilityState
        {
            /// <summary>低波动状态</summary>
            Low = 0,
            /// <summary>中等波动状态</summary>
            Medium = 1,
            /// <summary>高波动状态</summary>
            High = 2
        }

        /// <summary>
        /// 趋势方向枚举
        /// </summary>
        public enum TrendDirection
        {
            /// <summary>上升趋势</summary>
            Upward,
            /// <summary>下降趋势</summary>
            Downward,
            /// <summary>横盘趋势</summary>
            Sideways
        }

        /// <summary>
        /// 聚类分析结果
        /// </summary>
        public class ClusterAnalysisResult
        {
            /// <summary>聚类中心点（波动率值）</summary>
            public double[] ClusterCenters { get; set; }

            /// <summary>每个数据点的聚类标签</summary>
            public VolatilityState[] ClusterLabels { get; set; }

            /// <summary>状态转移概率矩阵</summary>
            public double[,] TransitionMatrix { get; set; }

            /// <summary>各状态平均持续时间</summary>
            public Dictionary<VolatilityState, double> AverageDuration { get; set; }

            /// <summary>当前波动率状态</summary>
            public VolatilityState CurrentState { get; set; }

            /// <summary>聚类收敛性</summary>
            public bool IsConverged { get; set; }

            /// <summary>迭代次数</summary>
            public int Iterations { get; set; }
        }

        /// <summary>
        /// 趋势分析结果
        /// </summary>
        public class TrendAnalysisResult
        {
            /// <summary>趋势方向</summary>
            public TrendDirection Direction { get; set; }

            /// <summary>趋势强度（0-1）</summary>
            public double Strength { get; set; }

            /// <summary>价格动量</summary>
            public double PriceMomentum { get; set; }

            /// <summary>波动率动量</summary>
            public double VolatilityMomentum { get; set; }

            /// <summary>综合趋势评分</summary>
            public double TrendScore { get; set; }

            /// <summary>趋势可信度</summary>
            public double Confidence { get; set; }
        }

        /// <summary>
        /// 波动率环境分析结果
        /// </summary>
        public class VolatilityEnvironmentResult
        {
            /// <summary>当前波动率状态</summary>
            public VolatilityState CurrentState { get; set; }

            /// <summary>预期下期状态</summary>
            public VolatilityState NextExpectedState { get; set; }

            /// <summary>状态转移概率</summary>
            public double StateTransitionProbability { get; set; }

            /// <summary>趋势分析结果</summary>
            public TrendAnalysisResult TrendAnalysis { get; set; }

            /// <summary>交易时机评分</summary>
            public double TradingOpportunityScore { get; set; }

            /// <summary>风险调整系数</summary>
            public double RiskAdjustmentFactor { get; set; }
        }

        #endregion

        #region 私有字段

        private ClusterAnalysisResult _lastClusterResult;
        private double[] _volatilityHistory;
        private double[] _priceHistory;
        private DateTime[] _timeStamps;

        #endregion

        #region 主要功能方法

        /// <summary>
        /// 执行K-means聚类分析
        /// 基于历史波动率数据识别低、中、高三种波动状态
        /// </summary>
        /// <param name="volatilityData">波动率时间序列</param>
        /// <returns>聚类分析结果</returns>
        public ClusterAnalysisResult PerformKMeansClusterAnalysis(double[] volatilityData)
        {
            if (volatilityData == null || volatilityData.Length < MIN_VOLATILITY_SAMPLES)
            {
                throw new ArgumentException($"波动率数据不足，至少需要{MIN_VOLATILITY_SAMPLES}个样本");
            }

            _volatilityHistory = (double[])volatilityData.Clone();

            // 初始化聚类中心
            double[] centers = InitializeClusterCenters(volatilityData);
            
            // K-means迭代
            var result = ExecuteKMeansIteration(volatilityData, centers);
            
            // 计算状态转移概率矩阵
            result.TransitionMatrix = CalculateTransitionMatrix(result.ClusterLabels);
            
            // 计算平均持续时间
            result.AverageDuration = CalculateAverageDuration(result.ClusterLabels);
            
            // 确定当前状态
            result.CurrentState = result.ClusterLabels.Last();

            _lastClusterResult = result;
            return result;
        }

        /// <summary>
        /// 计算趋势强度指标
        /// 基于价格动量和波动率的综合判断
        /// </summary>
        /// <param name="priceData">价格时间序列</param>
        /// <param name="volatilityData">波动率时间序列</param>
        /// <param name="window">计算窗口</param>
        /// <returns>趋势分析结果</returns>
        public TrendAnalysisResult CalculateTrendStrength(double[] priceData, 
            double[] volatilityData, int window = TREND_STRENGTH_WINDOW)
        {
            if (priceData == null || volatilityData == null)
                throw new ArgumentNullException("价格或波动率数据不能为空");

            if (priceData.Length != volatilityData.Length)
                throw new ArgumentException("价格数据和波动率数据长度必须一致");

            if (priceData.Length < window)
                throw new ArgumentException($"数据长度不足，至少需要{window}个数据点");

            _priceHistory = (double[])priceData.Clone();

            var result = new TrendAnalysisResult();

            // 计算价格动量
            result.PriceMomentum = CalculatePriceMomentum(priceData, window);
            
            // 计算波动率动量
            result.VolatilityMomentum = CalculateVolatilityMomentum(volatilityData, window);
            
            // 计算趋势强度
            result.Strength = CalculateTrendStrengthValue(result.PriceMomentum, result.VolatilityMomentum);
            
            // 确定趋势方向
            result.Direction = DetermineTrendDirection(result.PriceMomentum, result.Strength);
            
            // 计算综合评分
            result.TrendScore = CalculateCompositeTrendScore(result);
            
            // 计算可信度
            result.Confidence = CalculateTrendConfidence(result.Strength, volatilityData, window);

            return result;
        }

        /// <summary>
        /// 检测状态切换点
        /// 识别波动率状态的转换时机
        /// </summary>
        /// <param name="recentVolatility">最近的波动率序列</param>
        /// <param name="threshold">切换检测阈值</param>
        /// <returns>是否检测到状态切换</returns>
        public bool DetectStateSwitch(double[] recentVolatility, double threshold = TRANSITION_SMOOTHING_FACTOR)
        {
            if (_lastClusterResult == null)
                throw new InvalidOperationException("必须先执行聚类分析");

            if (recentVolatility == null || recentVolatility.Length < 5)
                return false;

            // 计算最近波动率与各聚类中心的距离
            double[] distances = new double[VOLATILITY_CLUSTERS];
            double currentVol = recentVolatility.Last();

            for (int i = 0; i < VOLATILITY_CLUSTERS; i++)
            {
                distances[i] = Math.Abs(currentVol - _lastClusterResult.ClusterCenters[i]);
            }

            // 找到最近的聚类中心
            int closestCluster = Array.IndexOf(distances, distances.Min());
            VolatilityState newState = (VolatilityState)closestCluster;

            // 检查是否发生状态切换
            bool stateChanged = newState != _lastClusterResult.CurrentState;

            // 使用平滑系数减少误报
            if (stateChanged)
            {
                double switchProbability = 1.0 - distances[closestCluster] / distances.Max();
                return switchProbability > threshold;
            }

            return false;
        }

        /// <summary>
        /// 提供波动率环境分类和趋势方向综合判断
        /// </summary>
        /// <param name="priceData">价格数据</param>
        /// <param name="volatilityData">波动率数据</param>
        /// <returns>波动率环境分析结果</returns>
        public VolatilityEnvironmentResult AnalyzeVolatilityEnvironment(double[] priceData, 
            double[] volatilityData)
        {
            // 执行聚类分析
            var clusterResult = PerformKMeansClusterAnalysis(volatilityData);
            
            // 计算趋势强度
            var trendResult = CalculateTrendStrength(priceData, volatilityData);

            var result = new VolatilityEnvironmentResult
            {
                CurrentState = clusterResult.CurrentState,
                TrendAnalysis = trendResult
            };

            // 预测下期状态
            result.NextExpectedState = PredictNextState(clusterResult);
            result.StateTransitionProbability = GetTransitionProbability(
                clusterResult.CurrentState, result.NextExpectedState, clusterResult.TransitionMatrix);

            // 计算交易时机评分
            result.TradingOpportunityScore = CalculateTradingOpportunityScore(result);
            
            // 计算风险调整系数
            result.RiskAdjustmentFactor = CalculateRiskAdjustmentFactor(result);

            return result;
        }

        #endregion

        #region 私有辅助方法

        /// <summary>
        /// 初始化K-means聚类中心
        /// </summary>
        private double[] InitializeClusterCenters(double[] data)
        {
            double[] centers = new double[VOLATILITY_CLUSTERS];
            
            // 使用分位数初始化聚类中心
            var sortedData = data.OrderBy(x => x).ToArray();
            centers[0] = sortedData[(int)(sortedData.Length * 0.25)]; // 低波动
            centers[1] = sortedData[(int)(sortedData.Length * 0.5)];  // 中等波动
            centers[2] = sortedData[(int)(sortedData.Length * 0.75)]; // 高波动

            return centers;
        }

        /// <summary>
        /// 执行K-means迭代算法
        /// </summary>
        private ClusterAnalysisResult ExecuteKMeansIteration(double[] data, double[] initialCenters)
        {
            double[] centers = (double[])initialCenters.Clone();
            VolatilityState[] labels = new VolatilityState[data.Length];
            bool converged = false;
            int iteration = 0;

            for (iteration = 0; iteration < KMEANS_MAX_ITERATIONS && !converged; iteration++)
            {
                // 分配数据点到最近的聚类中心
                for (int i = 0; i < data.Length; i++)
                {
                    double minDistance = double.MaxValue;
                    int closestCenter = 0;

                    for (int j = 0; j < VOLATILITY_CLUSTERS; j++)
                    {
                        double distance = Math.Abs(data[i] - centers[j]);
                        if (distance < minDistance)
                        {
                            minDistance = distance;
                            closestCenter = j;
                        }
                    }

                    labels[i] = (VolatilityState)closestCenter;
                }

                // 更新聚类中心
                double[] newCenters = new double[VOLATILITY_CLUSTERS];
                for (int j = 0; j < VOLATILITY_CLUSTERS; j++)
                {
                    var clusterPoints = data.Where((x, i) => labels[i] == (VolatilityState)j).ToArray();
                    if (clusterPoints.Length > 0)
                    {
                        newCenters[j] = clusterPoints.Average();
                    }
                    else
                    {
                        newCenters[j] = centers[j];
                    }
                }

                // 检查收敛
                converged = true;
                for (int j = 0; j < VOLATILITY_CLUSTERS; j++)
                {
                    if (Math.Abs(newCenters[j] - centers[j]) > KMEANS_CONVERGENCE_TOLERANCE)
                    {
                        converged = false;
                        break;
                    }
                }

                centers = newCenters;
            }

            return new ClusterAnalysisResult
            {
                ClusterCenters = centers,
                ClusterLabels = labels,
                IsConverged = converged,
                Iterations = iteration
            };
        }

        /// <summary>
        /// 计算状态转移概率矩阵
        /// </summary>
        private double[,] CalculateTransitionMatrix(VolatilityState[] states)
        {
            double[,] transitionMatrix = new double[VOLATILITY_CLUSTERS, VOLATILITY_CLUSTERS];
            int[,] transitionCounts = new int[VOLATILITY_CLUSTERS, VOLATILITY_CLUSTERS];

            // 统计状态转移次数
            for (int i = 0; i < states.Length - 1; i++)
            {
                int currentState = (int)states[i];
                int nextState = (int)states[i + 1];
                transitionCounts[currentState, nextState]++;
            }

            // 计算转移概率
            for (int i = 0; i < VOLATILITY_CLUSTERS; i++)
            {
                int totalTransitions = 0;
                for (int j = 0; j < VOLATILITY_CLUSTERS; j++)
                {
                    totalTransitions += transitionCounts[i, j];
                }

                for (int j = 0; j < VOLATILITY_CLUSTERS; j++)
                {
                    if (totalTransitions > 0)
                    {
                        transitionMatrix[i, j] = (double)transitionCounts[i, j] / totalTransitions;
                    }
                    else
                    {
                        transitionMatrix[i, j] = i == j ? 1.0 : 0.0; // 对角矩阵默认值
                    }
                }
            }

            return transitionMatrix;
        }

        /// <summary>
        /// 计算各状态平均持续时间
        /// </summary>
        private Dictionary<VolatilityState, double> CalculateAverageDuration(VolatilityState[] states)
        {
            var durations = new Dictionary<VolatilityState, List<int>>();
            
            // 初始化
            foreach (VolatilityState state in Enum.GetValues(typeof(VolatilityState)))
            {
                durations[state] = new List<int>();
            }

            // 计算每个状态的持续时间
            if (states.Length > 0)
            {
                VolatilityState currentState = states[0];
                int duration = 1;

                for (int i = 1; i < states.Length; i++)
                {
                    if (states[i] == currentState)
                    {
                        duration++;
                    }
                    else
                    {
                        durations[currentState].Add(duration);
                        currentState = states[i];
                        duration = 1;
                    }
                }
                durations[currentState].Add(duration);
            }

            // 计算平均值
            var averageDurations = new Dictionary<VolatilityState, double>();
            foreach (var kvp in durations)
            {
                averageDurations[kvp.Key] = kvp.Value.Count > 0 ? kvp.Value.Average() : 0.0;
            }

            return averageDurations;
        }

        /// <summary>
        /// 计算价格动量
        /// </summary>
        private double CalculatePriceMomentum(double[] priceData, int window)
        {
            if (priceData.Length < window)
                return 0.0;

            double[] recentPrices = priceData.Skip(priceData.Length - window).ToArray();
            double startPrice = recentPrices[0];
            double endPrice = recentPrices.Last();

            // 价格变化率
            double priceChange = (endPrice - startPrice) / startPrice;
            
            // 计算趋势一致性
            int positiveChanges = 0;
            for (int i = 1; i < recentPrices.Length; i++)
            {
                if (recentPrices[i] > recentPrices[i - 1])
                    positiveChanges++;
            }
            
            double trendConsistency = (double)positiveChanges / (recentPrices.Length - 1);
            
            // 综合动量 = 价格变化率 × 趋势一致性
            return priceChange * (2 * trendConsistency - 1);
        }

        /// <summary>
        /// 计算波动率动量
        /// </summary>
        private double CalculateVolatilityMomentum(double[] volatilityData, int window)
        {
            if (volatilityData.Length < window)
                return 0.0;

            double[] recentVol = volatilityData.Skip(volatilityData.Length - window).ToArray();
            
            // 计算波动率变化趋势
            double[] volChanges = new double[recentVol.Length - 1];
            for (int i = 1; i < recentVol.Length; i++)
            {
                volChanges[i - 1] = (recentVol[i] - recentVol[i - 1]) / recentVol[i - 1];
            }

            return volChanges.Average();
        }

        /// <summary>
        /// 计算趋势强度值
        /// </summary>
        private double CalculateTrendStrengthValue(double priceMomentum, double volatilityMomentum)
        {
            // 趋势强度 = |价格动量| - |波动率动量| 
            // 价格动量大而波动率动量小表示强趋势
            double strength = Math.Abs(priceMomentum) - Math.Abs(volatilityMomentum);
            
            // 标准化到0-1区间
            return Math.Max(0.0, Math.Min(1.0, (strength + 1.0) / 2.0));
        }

        /// <summary>
        /// 确定趋势方向
        /// </summary>
        private TrendDirection DetermineTrendDirection(double priceMomentum, double trendStrength)
        {
            if (trendStrength < TREND_STRENGTH_THRESHOLD)
                return TrendDirection.Sideways;

            return priceMomentum > 0 ? TrendDirection.Upward : TrendDirection.Downward;
        }

        /// <summary>
        /// 计算综合趋势评分
        /// </summary>
        private double CalculateCompositeTrendScore(TrendAnalysisResult trend)
        {
            double baseScore = trend.Strength;
            
            // 方向性加权
            double directionWeight = trend.Direction == TrendDirection.Sideways ? 0.5 : 1.0;
            
            // 动量一致性加权
            double momentumConsistency = trend.PriceMomentum * trend.VolatilityMomentum > 0 ? 1.2 : 0.8;
            
            return Math.Max(0.0, Math.Min(1.0, baseScore * directionWeight * momentumConsistency));
        }

        /// <summary>
        /// 计算趋势可信度
        /// </summary>
        private double CalculateTrendConfidence(double trendStrength, double[] volatilityData, int window)
        {
            // 基础可信度基于趋势强度
            double baseConfidence = trendStrength;
            
            // 波动率稳定性调整
            double[] recentVol = volatilityData.Skip(volatilityData.Length - window).ToArray();
            double volStability = 1.0 / (1.0 + CalculateCoefficientOfVariation(recentVol));
            
            return Math.Max(0.0, Math.Min(1.0, baseConfidence * volStability));
        }

        /// <summary>
        /// 预测下期状态
        /// </summary>
        private VolatilityState PredictNextState(ClusterAnalysisResult clusterResult)
        {
            int currentStateIndex = (int)clusterResult.CurrentState;
            double maxProbability = 0.0;
            int nextStateIndex = currentStateIndex;

            for (int j = 0; j < VOLATILITY_CLUSTERS; j++)
            {
                double probability = clusterResult.TransitionMatrix[currentStateIndex, j];
                if (probability > maxProbability)
                {
                    maxProbability = probability;
                    nextStateIndex = j;
                }
            }

            return (VolatilityState)nextStateIndex;
        }

        /// <summary>
        /// 获取状态转移概率
        /// </summary>
        private double GetTransitionProbability(VolatilityState fromState, VolatilityState toState, 
            double[,] transitionMatrix)
        {
            return transitionMatrix[(int)fromState, (int)toState];
        }

        /// <summary>
        /// 计算交易时机评分
        /// </summary>
        private double CalculateTradingOpportunityScore(VolatilityEnvironmentResult env)
        {
            double baseScore = 0.5;
            
            // 低波动环境加分（有利于交易）
            if (env.CurrentState == VolatilityState.Low)
                baseScore += 0.3;
            else if (env.CurrentState == VolatilityState.High)
                baseScore -= 0.2;
            
            // 强趋势加分
            baseScore += env.TrendAnalysis.Strength * 0.3;
            
            // 趋势可信度加权
            baseScore *= env.TrendAnalysis.Confidence;
            
            return Math.Max(0.0, Math.Min(1.0, baseScore));
        }

        /// <summary>
        /// 计算风险调整系数
        /// </summary>
        private double CalculateRiskAdjustmentFactor(VolatilityEnvironmentResult env)
        {
            double baseFactor = 1.0;
            
            // 根据波动状态调整
            switch (env.CurrentState)
            {
                case VolatilityState.Low:
                    baseFactor = 1.2; // 低波动可适度提高仓位
                    break;
                case VolatilityState.High:
                    baseFactor = 0.7; // 高波动降低仓位
                    break;
                case VolatilityState.Medium:
                    baseFactor = 1.0;
                    break;
            }
            
            // 趋势强度调整
            baseFactor *= (0.8 + 0.4 * env.TrendAnalysis.Strength);
            
            return Math.Max(0.3, Math.Min(1.5, baseFactor));
        }

        /// <summary>
        /// 计算变异系数
        /// </summary>
        private double CalculateCoefficientOfVariation(double[] data)
        {
            if (data.Length == 0) return 0.0;
            
            double mean = data.Average();
            if (Math.Abs(mean) < CALCULATION_PRECISION) return 0.0;
            
            double variance = data.Select(x => Math.Pow(x - mean, 2)).Average();
            double standardDeviation = Math.Sqrt(variance);
            
            return standardDeviation / Math.Abs(mean);
        }

        #endregion

        #region 公开属性和状态查询

        /// <summary>
        /// 获取最新的聚类分析结果
        /// </summary>
        public ClusterAnalysisResult LastClusterResult => _lastClusterResult;

        /// <summary>
        /// 获取当前分析器状态
        /// </summary>
        /// <returns>分析器状态信息</returns>
        public string GetAnalyzerStatus()
        {
            return $"VolatilityClusterAnalyzer状态：" +
                   $"已分析数据点：{_volatilityHistory?.Length ?? 0}，" +
                   $"当前波动状态：{_lastClusterResult?.CurrentState.ToString() ?? "未知"}，" +
                   $"聚类收敛：{_lastClusterResult?.IsConverged ?? false}";
        }

        #endregion
    }
}
